package com.minisoft.activity;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;

/**
 * @author JueSu
 * @description: TODO
 * @date 2023/2/15 13:13
 */
public class Lottery {
    public static void main(String[] args) {

    }
    public static int lottery(List<Double> originalRates) {
        if (originalRates == null || originalRates.isEmpty()) {
            return -1;
        }

        int size = originalRates.size();

        // 验证概率列表中不包含非正数
        for (int i = 0; i < size; i++) {
            if (originalRates.get(i) <= 0) {
                throw new IllegalArgumentException("Invalid probability value at index " + i);
            }
        }

        // 计算概率总和
        double sumRate = 0d;
        for (int i = 0; i < size; i++) {
            sumRate += originalRates.get(i);
        }

        // 计算每个物品的概率范围
        List<Double> probabilityRanges = new ArrayList<>(size);
        double tempSumRate = 0d;
        for (int i = 0; i < size; i++) {
            tempSumRate += originalRates.get(i);
            double probability = tempSumRate / sumRate;
            probabilityRanges.add(probability);
        }

        // 生成随机数，并查找所选物品的索引
        double randomNumber = ThreadLocalRandom.current().nextDouble();
        int itemIndex = binarySearch(probabilityRanges, randomNumber);

        return itemIndex;
    }

    // 使用二分查找算法查找随机数所在的概率范围
    private static int binarySearch(List<Double> list, double key) {
        int low = 0;
        int high = list.size() - 1;

        while (low <= high) {
            int mid = (low + high) >>> 1;
            double midVal = list.get(mid);

            if (midVal < key) {
                low = mid + 1;
            } else if (midVal > key) {
                high = mid - 1;
            } else {
                return mid;
            }
        }

        return low;
    }

    public static int draw(List<Double> probabilities) {
        double rand = new Random().nextDouble();
        double cumulativeProbability = 0.0;
        for (int i = 0; i < probabilities.size(); i++) {
            cumulativeProbability += probabilities.get(i);
            if (rand < cumulativeProbability) {
                return i;
            }
        }
        return -1;
    }

}
